/** * Copyright 2011 Kevin J. Jones (http://www.kevinjjones.co.uk) * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package uk.co.kevinjjones; import info.monitorenter.gui.chart.IAxis; import info.monitorenter.gui.chart.IAxis.AxisTitle; import info.monitorenter.gui.chart.IRangePolicy; import info.monitorenter.gui.chart.ITrace2D; import info.monitorenter.gui.chart.ZoomableChart; import info.monitorenter.gui.chart.axis.AAxis; import info.monitorenter.gui.chart.axis.AxisLinear; import info.monitorenter.gui.chart.rangepolicies.RangePolicyFixedViewport; import info.monitorenter.gui.chart.rangepolicies.RangePolicyForcedPoint; import info.monitorenter.util.Range; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.SortedSet; import javax.swing.*; import javax.swing.plaf.FontUIResource; import net.iharder.dnd.FileDrop; import uk.co.kevinjjones.model.BasicError; import uk.co.kevinjjones.model.ROStream; import uk.co.kevinjjones.model.WithError; import uk.co.kevinjjones.vehicle.AFRStream; import uk.co.kevinjjones.vehicle.SpeedStream; import uk.co.kevinjjones.vehicle.TempStream; public class DTAPlot { // Main backgroud colour private static Color BKGDCOLOUR=new Color(0x041731); // All the UI components private ZoomableChart _chart; private JScrollBar _chartHScroll; private JScrollBar _chartVScroll; private JList _messages; private DefaultListModel _messagesModel; private JComboBox _lapCombo; private JCheckBox _autoSplitCheck; private JCheckBox _speedCheck; private JCheckBox _tpsCheck; private JCheckBox _mapCheck; private JCheckBox _rpmCheck; private JCheckBox _afrCheck; private JCheckBox _turboCheck; private JCheckBox _waterTempCheck; private JCheckBox _oilTempCheck; private JCheckBox _airTempCheck; private JCheckBox _wheelSlipCheck; //private JCheckBox _timeSlipCheck; private JButton _traceBtn; private JButton _clearBtn; private JButton _resetZoomBtn; private JButton _optionsBtn; private boolean _ignoreEvents = false; // Entry, loads any files passed on command line public static void main(String[] args) { DTAPlot.initializeFontSize(125); DTAPlot p = new DTAPlot(); p.run(); // Load any command line files RunManager mgr = RunManager.getInstance(); for (int i = 0; i < args.length; i++) { p.loadFile(new File(args[i])); } } private DTAPlot() { super(); } /** * Chart color picker * @param index - What color # to pick */ private static Color getColor(int index) { Color c = Color.BLACK; switch (index % 6) { case 0: c = new Color(228, 26, 28); break; case 1: c = new Color(55, 126, 184); break; case 2: c = new Color(77, 175, 74); break; case 3: c = new Color(152, 78, 163); break; case 4: c = new Color(255, 127, 0); break; case 5: c = new Color(166, 86, 40); break; } return c; } /** * Get next colour to use for a trace. * Picks the least used color in existing traces. */ private Color getNextColor() { // Find least used color int[] count = new int[6]; SortedSet<ITrace2D> traces = _chart.getTraces(); for (ITrace2D trace : traces) { for (int i = 0; i < 6; i++) { if (trace.getColor().equals(getColor(i))) { count[i] += 1; break; } } } int lowest = 0; int lowestCount = count[lowest]; for (int i = 1; i < 6; i++) { if (count[i] < lowestCount) { lowest = i; lowestCount = count[i]; } } return getColor(lowest); } /** * Setup UI components. */ private void run() { // Create The main frame sized to be OK on netbook 800x600 displays final JFrame frame = new JFrame("DTA Plot v2.1 - http://westboost.github.com/"); frame.setMinimumSize(new Dimension(400, 400)); frame.setPreferredSize(new Dimension(1280, 720)); RunManager.getInstance().setFrame(frame); final Container content = frame.getContentPane(); content.setBackground(BKGDCOLOUR); // Top level layout is Spring SpringLayout layout = new SpringLayout(); content.setLayout(layout); // Construct the menu area, min width = 100px JPanel menuArea = new JPanel(); menuArea.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); GridLayout menuLayout = new GridLayout(0, 1, 0, 5); menuArea.setLayout(menuLayout); menuArea.setMaximumSize(new Dimension(100, 0)); menuArea.add(new JLabel("Select Session/Run")); menuArea.add(_lapCombo=new JComboBox()); menuArea.add(_autoSplitCheck = new JCheckBox("Auto Split Runs")); menuArea.add(_speedCheck = new JCheckBox("Speed")); // menuArea.add(_timeSlipCheck = new JCheckBox("Time Lag")); menuArea.add(_wheelSlipCheck = new JCheckBox("Wheel Slip")); menuArea.add(_tpsCheck = new JCheckBox("Throttle")); menuArea.add(_mapCheck = new JCheckBox("MAP")); menuArea.add(_rpmCheck = new JCheckBox("RPM")); menuArea.add(_turboCheck = new JCheckBox("Turbo")); menuArea.add(_afrCheck = new JCheckBox("AFR")); menuArea.add(_waterTempCheck = new JCheckBox("Water Temp")); menuArea.add(_oilTempCheck = new JCheckBox("Oil Temp")); menuArea.add(_airTempCheck = new JCheckBox("Air Temp")); menuArea.add(new JLabel("")); // Just a spacer menuArea.add(_clearBtn = new JButton("Clear Traces")); menuArea.add(_resetZoomBtn = new JButton("Reset Zoom")); menuArea.add(_traceBtn = new JButton("Other Traces...")); menuArea.add(_optionsBtn = new JButton("Options...")); // Construct the chart JPanel chartArea = new JPanel(); BorderLayout chartLayout = new BorderLayout(); chartArea.setLayout(chartLayout); _chart = new ZoomableChart(); _chart.getAxesXBottom().get(0).setTitle("Time"); _chart.getAxesXBottom().get(0).setPaintGrid(true); _chart.getAxesYLeft().get(0).setTitle(""); _chart.getAxesYLeft().get(0).setPaintGrid(true); chartArea.add(_chart, BorderLayout.CENTER); _chartHScroll = new JScrollBar(JScrollBar.HORIZONTAL); chartArea.add(_chartHScroll, BorderLayout.PAGE_END); _chartVScroll = new JScrollBar(JScrollBar.VERTICAL); chartArea.add(_chartVScroll, BorderLayout.LINE_END); // And the message area _messagesModel = new DefaultListModel(); _messagesModel.addElement(new BasicError(BasicError.WARN, "To load a logfile, drag and drop onto graph")); _messages = new JList(_messagesModel); _messages.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); _messages.setLayoutOrientation(JList.VERTICAL); _messages.setVisibleRowCount(-1); BasicErrorRenderer der = new BasicErrorRenderer(frame); _messages.setFixedCellHeight(20); _messages.setCellRenderer(der); _messages.addListSelectionListener(der); _messages.validate(); JScrollPane listScroller = new JScrollPane(_messages); listScroller.setBorder(null); // Build up content.add(menuArea); content.add(listScroller); content.add(chartArea); // Loads of constraints to align the three areas :-) layout.putConstraint(SpringLayout.WEST, menuArea, 5, SpringLayout.WEST, content); layout.putConstraint(SpringLayout.NORTH, menuArea, 5, SpringLayout.NORTH, content); layout.putConstraint(SpringLayout.SOUTH, menuArea, -5, SpringLayout.SOUTH, content); layout.putConstraint(SpringLayout.WEST, listScroller, 5, SpringLayout.EAST, menuArea); layout.putConstraint(SpringLayout.NORTH, listScroller, -85, SpringLayout.SOUTH, content); layout.putConstraint(SpringLayout.EAST, listScroller, -5, SpringLayout.EAST, content); layout.putConstraint(SpringLayout.SOUTH, listScroller, -5, SpringLayout.SOUTH, content); layout.putConstraint(SpringLayout.WEST, chartArea, 5, SpringLayout.EAST, menuArea); layout.putConstraint(SpringLayout.EAST, chartArea, -5, SpringLayout.EAST, content); layout.putConstraint(SpringLayout.NORTH, chartArea, 5, SpringLayout.NORTH, content); layout.putConstraint(SpringLayout.SOUTH, chartArea, -5, SpringLayout.NORTH, listScroller); // Handle file dropping FileDrop fd = new FileDrop(frame, new FileDrop.Listener() { @Override public void filesDropped(java.io.File[] files) { RunManager mgr = RunManager.getInstance(); for (int i = 0; i < files.length; i++) { loadFile(files[i]); } } }); // Handle clicks _chart.addMouseListener( new MouseAdapter() { @Override public void mouseReleased(final MouseEvent m) { if (!_ignoreEvents) { resetChartScroll(); } } }); _chartHScroll.addAdjustmentListener( new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent a) { if (!_ignoreEvents) { scrollHChart(a.getValue()); } } }); _chartVScroll.addAdjustmentListener( new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent a) { if (!_ignoreEvents) { scrollVChart(a.getValue()); } } }); _lapCombo.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!_ignoreEvents) { setOptions(); } } }); _traceBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { otherTraces(frame, getSelectedRun()); } }); _clearBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { removeTraces(); _chart.zoomAll(); List<IAxis> axisl = _chart.getAxesYLeft(); for (int a = 0; a < axisl.size(); a++) { axisl.get(a).setRangePolicy(new RangePolicyForcedPoint(0)); } resetChartScroll(); } }); _resetZoomBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { _chart.zoomAll(); List<IAxis> axisl = _chart.getAxesYLeft(); for (int a = 0; a < axisl.size(); a++) { axisl.get(a).setRangePolicy(new RangePolicyForcedPoint(0)); } resetChartScroll(); } }); _optionsBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setGlobalOptions(frame); } }); _autoSplitCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { setAutoSplit(content, e.getStateChange() == ItemEvent.SELECTED); } }); _speedCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, SpeedStream.NAME, e.getStateChange() == ItemEvent.SELECTED); } } }); _tpsCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, Log.THROT_STREAM, e.getStateChange() == ItemEvent.SELECTED); } } }); _mapCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, Log.MAP_STREAM, e.getStateChange() == ItemEvent.SELECTED); } } }); _rpmCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, Log.RPM_STREAM, e.getStateChange() == ItemEvent.SELECTED); } } }); /* _timeSlipCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); timeSlipTrace(run, e.getStateChange() == ItemEvent.SELECTED); } } }); * */ _turboCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, Log.TURB_STREAM, e.getStateChange() == ItemEvent.SELECTED); } } }); _afrCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, AFRStream.AFR_NAME, e.getStateChange() == ItemEvent.SELECTED); } } }); _wheelSlipCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, Log.SLIP_STREAM, e.getStateChange() == ItemEvent.SELECTED); } } }); _oilTempCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, TempStream.OIL_NAME, e.getStateChange() == ItemEvent.SELECTED); } } }); _waterTempCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, TempStream.WATER_NAME, e.getStateChange() == ItemEvent.SELECTED); } } }); _airTempCheck.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (!_ignoreEvents) { RunManager.Run run = getSelectedRun(); toggleTrace(run, TempStream.AIR_NAME, e.getStateChange() == ItemEvent.SELECTED); } } }); // Enable the termination button [cross on the upper right edge]: frame.addWindowListener( new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); // All ready to go frame.pack(); frame.setVisible(true); setOptions(); } /** * Load a log file. * Errors are displayed on the message panel so no return needed. * @param file */ private void loadFile(File file) { RunManager mgr = RunManager.getInstance(); WithError<Boolean, BasicError> ok = new WithError(true); try { mgr.addLogfile(file, ok); } catch (IOException ex) { ok.addError(new BasicError(ex)); } ArrayList<BasicError> errs = ok.errors(); for (BasicError e : errs) { _messagesModel.add(0, e); } if (ok.value().booleanValue() == true) { addedLogs(); } } /** * Display selection dialog for other traces for current run. * @param frame Frame to attach dialog to * @param run The current run */ private void otherTraces(JFrame frame, RunManager.Run run) { final JDialog dialog = new JDialog(frame, "Other Traces", true); JPanel traceArea = new JPanel(); GridLayout layout = new GridLayout(0, 4); traceArea.setLayout(layout); final ArrayList<JCheckBox> checks = new ArrayList(); for (int t = 0; t < run.streamCount(); t++) { ROStream s = run.getStream(t); // Ignore streams displayed on UI if (s.name().equals(Log.SESSION_STREAM) || s.name().equals(Log.TIME_STREAM) || s.name().equals(SpeedStream.NAME) || s.name().equals(Log.THROT_STREAM) || s.name().equals(Log.MAP_STREAM) || s.name().equals(Log.RPM_STREAM) || s.name().equals(Log.TURB_STREAM) || s.name().equals(AFRStream.AFR_NAME) || s.name().equals(TempStream.WATER_NAME) || s.name().equals(TempStream.OIL_NAME) || s.name().equals(TempStream.AIR_NAME) || s.name().equals(Log.SLIP_STREAM)) { continue; } // Ignore streams that have been hidden if (s.getMeta("hide").equals("true")) { continue; } JCheckBox cb = new JCheckBox(s.name()); cb.setSelected(findTrace(run.name() + " " + s.description())!=null); checks.add(cb); traceArea.add(cb); } JPanel buttonArea = new JPanel(); FlowLayout buttonLayout = new FlowLayout(FlowLayout.RIGHT); buttonArea.setLayout(buttonLayout); JButton clearBtn = new JButton("Clear All"); JButton applyBtn = new JButton("Apply"); JButton okBtn = new JButton("OK"); buttonArea.add(clearBtn); buttonArea.add(applyBtn); buttonArea.add(okBtn); clearBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (int i = 0; i < checks.size(); i++) { checks.get(i).setSelected(false); } } }); applyBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { RunManager.Run run = getSelectedRun(); for (int i = 0; i < checks.size(); i++) { toggleTrace(run, checks.get(i).getText(), checks.get(i).isSelected()); } } }); okBtn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { RunManager.Run run = getSelectedRun(); for (int i = 0; i < checks.size(); i++) { toggleTrace(run, checks.get(i).getText(), checks.get(i).isSelected()); } dialog.setVisible(false); } }); JPanel dialogPanel = new JPanel(); BorderLayout dialogLayout = new BorderLayout(); dialogPanel.setLayout(dialogLayout); dialogPanel.add(traceArea, BorderLayout.CENTER); dialogPanel.add(buttonArea, BorderLayout.PAGE_END); Container content = dialog.getContentPane(); content.add(dialogPanel); dialog.pack(); dialog.setLocationRelativeTo(frame); dialog.setVisible(true); } /** * Display selection dialog for global options * @param frame Frame to attach dialog to */ private void setGlobalOptions(JFrame frame) { JDialog dialog = new JDialog(frame, "DTA System Units", true); Container content = dialog.getContentPane(); OptionsDialog oDlg = new OptionsDialog(); content.add(oDlg); dialog.pack(); dialog.setLocationRelativeTo(frame); dialog.setVisible(true); } private void setAutoSplit(Container content, boolean on) { RunManager.getInstance().setAutoSplit(on); } private synchronized void addedLogs() { RunManager mgr = RunManager.getInstance(); RunManager.Run[] runs = mgr.getRuns(); for (int l = 0; l < runs.length; l++) { RunManager.Run r = runs[l]; int at = -1; for (int i = 0; i < _lapCombo.getItemCount(); i++) { if (((String) _lapCombo.getItemAt(i)).equals(r.name())) { at = i; break; } } if (at == -1) { _lapCombo.addItem(r.name()); if (r.isSplit()) { toggleTrace(r, SpeedStream.NAME, true); } } } _chart.zoomAll(); resetChartScroll(); setOptions(); } private void resetChartScroll() { IAxis xa = _chart.getAxisX(); if (xa != null) { double range = xa.getMaxValue() - xa.getMinValue(); double shown = xa.getMax() - xa.getMin(); if (range > 0 && range > shown) { int steps = 10 * (int) Math.ceil(range / shown); double rangePerStep = range / steps; double startOffset = xa.getMin() - xa.getMinValue(); _ignoreEvents = true; _chartHScroll.setVisible(true); _chartHScroll.setMinimum(0); _chartHScroll.setValue((int) Math.ceil(startOffset / rangePerStep)); _chartHScroll.setMaximum(steps); _ignoreEvents = false; } else { _chartHScroll.setVisible(false); } } // Scan all axis for smallest viewport vs the axis range int steps = 0; IAxis ya = null; List<IAxis> axisl = _chart.getAxesYLeft(); for (int a = 0; a < axisl.size(); a++) { IAxis ax = axisl.get(a); double range = ax.getMaxValue() - Math.min(0, ax.getMinValue()); double shown = ax.getMax() - ax.getMin(); if (range > 0 && range > shown) { int s = 10 * (int) Math.ceil(range / shown); if (s > steps) { steps = s; ya = ax; } } } // Now set per that axis _chartVScroll.setVisible(false); if (ya != null) { double range = ya.getMaxValue() - Math.min(0, ya.getMinValue()); double shown = ya.getMax() - ya.getMin(); if (range > 0 && range > shown) { double rangePerStep = range / steps; double startOffset = ya.getMin() - Math.min(0, ya.getMinValue()); _ignoreEvents = true; _chartVScroll.setVisible(true); _chartVScroll.setMinimum(0); _chartVScroll.setMaximum(steps); _chartVScroll.setValue(steps - 10 - (int) Math.ceil(startOffset / rangePerStep)); _ignoreEvents = false; } } } private void scrollHChart(int value) { IAxis xa = _chart.getAxisX(); if (xa != null && _chartHScroll.isVisible()) { double range = xa.getMaxValue() - xa.getMinValue(); double shown = xa.getMax() - xa.getMin(); int steps = 10 * (int) Math.ceil(range / shown); double rangePerStep = range / steps; double min = value * rangePerStep; double max = min + (xa.getMax() - xa.getMin()); _chart.zoom(min, max); } } private void scrollVChart(int value) { List<IAxis> axisl = _chart.getAxesYLeft(); for (int a = 0; a < axisl.size(); a++) { IAxis ya = axisl.get(a); if (ya != null && _chartVScroll.isVisible()) { double range = ya.getMaxValue() - Math.min(0, ya.getMinValue()); double shown = ya.getMax() - ya.getMin(); int steps = 10 * (int) Math.ceil(range / shown); double rangePerStep = range / steps; double min = (steps - 10 - value) * rangePerStep + Math.min(0, ya.getMinValue()); double max = min + (ya.getMax() - ya.getMin()); IRangePolicy zoomPolicy = new RangePolicyFixedViewport(new Range(min, max)); ya.setRangePolicy(zoomPolicy); } } } private synchronized RunManager.Run getSelectedRun() { String run = (String) _lapCombo.getSelectedItem(); RunManager mgr = RunManager.getInstance(); RunManager.Run[] runs = mgr.getRuns(); for (int l = 0; l < runs.length; l++) { RunManager.Run r = runs[l]; if (r.name().equals(run)) { return r; } } return null; } private synchronized void setOptions() { _autoSplitCheck.setSelected(RunManager.getInstance().isAutoSplit()); RunManager.Run run = getSelectedRun(); if (run != null) { _ignoreEvents = true; _speedCheck.setEnabled(run.log().hasStream(SpeedStream.NAME)); _tpsCheck.setEnabled(run.log().hasStream(Log.THROT_STREAM)); _mapCheck.setEnabled(run.log().hasStream(Log.MAP_STREAM)); _rpmCheck.setEnabled(run.log().hasStream(Log.RPM_STREAM)); //_timeSlipCheck.setEnabled(run.log().hasStream(Log.TimeSlip_STREAM)); _turboCheck.setEnabled(run.log().hasStream(Log.TURB_STREAM)); _afrCheck.setEnabled(run.log().hasStream(Log.LAMB_STREAM)); _waterTempCheck.setEnabled(run.log().hasStream(TempStream.WATER_NAME)); _oilTempCheck.setEnabled(run.log().hasStream(TempStream.OIL_NAME)); _airTempCheck.setEnabled(run.log().hasStream(TempStream.AIR_NAME)); _wheelSlipCheck.setEnabled(run.log().hasStream(Log.SLIP_STREAM)); _speedCheck.setSelected(false); _tpsCheck.setSelected(false); _mapCheck.setSelected(false); _rpmCheck.setSelected(false); //_timeSlipCheck.setSelected(false); _turboCheck.setSelected(false); _afrCheck.setSelected(false); _waterTempCheck.setSelected(false); _oilTempCheck.setSelected(false); _airTempCheck.setSelected(false); _wheelSlipCheck.setSelected(false); ITrace2D[] traces = _chart.getTraces().toArray(new ITrace2D[0]); String name = run.name(); for (int i = 0; i < traces.length; i++) { if (traces[i].getName().equals(name + " " + Log.getStreamDescription(SpeedStream.NAME))) { _speedCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(Log.THROT_STREAM))) { _tpsCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(Log.MAP_STREAM))) { _mapCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(Log.RPM_STREAM))) { _rpmCheck.setSelected(true); // } else if (traces[i].getName().equals(name + " Time Lag")) { // _timeSlipCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(Log.TURB_STREAM))) { _turboCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(AFRStream.AFR_NAME))) { _afrCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(TempStream.WATER_NAME))) { _waterTempCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(TempStream.OIL_NAME))) { _oilTempCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(TempStream.AIR_NAME))) { _airTempCheck.setSelected(true); } else if (traces[i].getName().equals(name + " " + Log.getStreamDescription(Log.SLIP_STREAM))) { _wheelSlipCheck.setSelected(true); } } _chart.setToolTipText("Select an area with mouse to zoom in"); _lapCombo.setToolTipText("Select run to change traces"); _ignoreEvents = false; } else { _speedCheck.setEnabled(false); _tpsCheck.setEnabled(false); _mapCheck.setEnabled(false); _rpmCheck.setEnabled(false); //_timeSlipCheck.setEnabled(false); _turboCheck.setEnabled(false); _afrCheck.setEnabled(false); _waterTempCheck.setEnabled(false); _oilTempCheck.setEnabled(false); _airTempCheck.setEnabled(false); _wheelSlipCheck.setEnabled(false); } } private synchronized ITrace2D findTrace(String name) { ITrace2D[] traces = _chart.getTraces().toArray(new ITrace2D[0]); for (int i = 0; i < traces.length; i++) { if (traces[i].getName().equals(name)) { return traces[i]; } } return null; } private synchronized ITrace2D findTraceContains(String substring) { ITrace2D[] traces = _chart.getTraces().toArray(new ITrace2D[0]); for (int i = 0; i < traces.length; i++) { if (traces[i].getName().contains(substring)) { return traces[i]; } } return null; } private synchronized IAxis getAxis(String label) { List<IAxis> axisl = _chart.getAxesYLeft(); IAxis axis = null; IAxis empty = null; for (int a = 0; a < axisl.size(); a++) { if (axisl.get(a).getTitle().equals(label)) { axis = axisl.get(a); break; } if (axisl.get(a).getTitle().length() == 0) { empty = axisl.get(a); } } if (axis == null) { axis = empty; if (axis == null) { AAxis a = new AxisLinear(); _chart.addAxisYLeft(a); axis = a; } axis.setAxisTitle(new AxisTitle(label)); axis.setRangePolicy(new RangePolicyForcedPoint(0)); } return axis; } private synchronized void cleanAxis(String label) { List<IAxis> axisl = _chart.getAxesYLeft(); for (int a = 0; a < axisl.size(); a++) { if (axisl.get(a).getTitle().equals(label)) { if (a == 0) { if (axisl.size() > 1) { // Swap traces from last to first axis IAxis last = axisl.get(axisl.size() - 1); _chart.removeAxisYLeft(last); ITrace2D[] traces = last.getTraces().toArray(new ITrace2D[0]); last.removeAllTraces(); axisl.get(0).setTitle(last.getTitle()); for (int i = 0; i < traces.length; i++) { axisl.get(0).addTrace(traces[i]); } } else { axisl.get(a).setTitle(""); } } else { _chart.removeAxisYLeft(axisl.get(a)); } } } } private synchronized void removeTraces() { _chart.removeAllTraces(); IAxis[] axisl = _chart.getAxesYLeft().toArray(new IAxis[0]); for (int a = 0; a < axisl.length; a++) { axisl[a].removeAllTraces(); if (a == 0) { axisl[a].setTitle(""); } else { _chart.removeAxisYLeft(axisl[a]); } } setOptions(); _chart.zoomAll(); } private synchronized void toggleTrace(RunManager.Run r, String streamName, boolean on) { ROStream s = r.getStream(streamName); assert(s!=null); String suffix = ""; if (s.units() != null && !s.units().isEmpty()) { suffix = " (" + s.units() + ")"; } String axisName = s.axis(); ITrace2D trace = findTrace(r.name() + " " + s.description()); if (on) { if (trace == null) { IAxis axis = getAxis(axisName + suffix); trace = new Trace(r.name() + " " + s.description()); trace.setColor(getNextColor()); trace.setStroke(new BasicStroke(2)); _chart.addTrace(trace, _chart.getAxesXBottom().get(0), axis); for (int i = 0; i < r.length(); i++) { trace.addPoint(i * 0.1, s.getNumeric(i)); } } } else { if (trace != null) { IAxis axis = getAxis(axisName + suffix); axis.removeTrace(trace); _chart.removeTrace(trace); if (findTraceContains(axisName) == null) { cleanAxis(axisName + suffix); } } } } /* * private synchronized void steerTrace(RunManager.Run r, boolean on) { * * String axisName="Steering Angle (+ve Right, -ve Left)"; String * traceName=r.name() + " Steering Angle"; ITrace2D trace = * findTrace(traceName); if (on) { if (trace == null) { IAxis axis = * getAxis(axisName); trace = new Trace(traceName); * trace.setColor(getNextColor()); _chart.addTrace(trace, * _chart.getAxesXBottom().get(0), axis); * * double[] avg=new double[5]; int at=0; for (int i = 0; i < r.length(); * i++) { //avg[at]=r.degrees(i); at=(at+1)%5; * * trace.addPoint(i * 0.1, (avg[0]+avg[1]+avg[2]+avg[3]+avg[4])/5); } } } * else { if (trace != null) { IAxis axis = getAxis(axisName); * axis.removeTrace(trace); _chart.removeTrace(trace); if * (findTraceContains(axisName) == null) { cleanAxis(axisName); } } } } * * private synchronized void latAccelTrace(RunManager.Run r, boolean on) { * * String axisName="Lat. Accel. (+ve Right, -ve Left)"; String * traceName=r.name() + " Lat. Accel."; ITrace2D trace = * findTrace(traceName); if (on) { if (trace == null) { IAxis axis = * getAxis(axisName); trace = new Trace(traceName); * trace.setColor(getNextColor()); _chart.addTrace(trace, * _chart.getAxesXBottom().get(0), axis); * * double[] avg=new double[5]; int at=0; for (int i = 0; i < r.length(); * i++) { //avg[at]=r.latAccel(i); at=(at+1)%5; * * trace.addPoint(i * 0.1, (avg[0]+avg[1]+avg[2]+avg[3]+avg[4])/5); } } } * else { if (trace != null) { IAxis axis = getAxis(axisName); * axis.removeTrace(trace); _chart.removeTrace(trace); if * (findTraceContains(axisName) == null) { cleanAxis(axisName); } } } } * * private synchronized void longAccelTrace(RunManager.Run r, boolean on) { * * String axisName="Long. Accel. (g)"; String traceName=r.name() + " Long. * Accel."; ITrace2D trace = findTrace(traceName); if (on) { if (trace == * null) { IAxis axis = getAxis(axisName); trace = new Trace(traceName); * trace.setColor(getNextColor()); _chart.addTrace(trace, * _chart.getAxesXBottom().get(0), axis); * * double[] avg=new double[5]; int at=0; for (int i = 0; i < r.length(); * i++) { //avg[at]=r.speedKPH(i); * * double a=avg[at]-avg[(at+1)%5]; a=a*1000/3600; a=a/0.5; a=a/9.8; * trace.addPoint(i * 0.1, a); at=(at+1)%5; } } } else { if (trace != null) * { IAxis axis = getAxis(axisName); axis.removeTrace(trace); * _chart.removeTrace(trace); if (findTraceContains(axisName) == null) { * cleanAxis(axisName); } } } } */ private synchronized void timeSlipTrace(RunManager.Run r, boolean on) { ITrace2D trace = findTrace(r.name() + " Time Lag"); if (on) { if (trace == null) { IAxis axis = getAxis("Time Lag (sec)"); trace = new Trace(r.name() + " Time Lag"); trace.setColor(getNextColor()); _chart.addTrace(trace, _chart.getAxesXBottom().get(0), axis); for (int i = 0; i < r.length(); i++) { //trace.addPoint(i * 0.1, r.timeSlip(i)); } } } else { if (trace != null) { IAxis axis = getAxis("Time Lag (sec)"); axis.removeTrace(trace); _chart.removeTrace(trace); if (findTraceContains("Time Lag") == null) { cleanAxis("Time Lag (sec)"); } } } } public static void initializeFontSize(int scale) { float multiplier = scale / 100.0f; UIDefaults defaults = UIManager.getDefaults(); int i = 0; for (Enumeration e = defaults.keys(); e.hasMoreElements(); i++) { Object key = e.nextElement(); Object value = defaults.get(key); if (value instanceof Font) { Font font = (Font) value; int newSize = Math.round(font.getSize() * multiplier); if (value instanceof FontUIResource) { UIManager.put(key, new FontUIResource(font.getName(), font.getStyle(), newSize)); } else { UIManager.put(key, new Font(font.getName(), font.getStyle(), newSize)); } } } } }